import _, { filter } from 'lodash';
import { Icon } from '@iconify/react';
import { sentenceCase } from 'change-case';
import React, {useState, useEffect, useContext, useReducer} from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { useFormik } from "formik";
// material
import {
  Card,
  Table,
  Stack,
  Avatar,
  Button,
  Checkbox,
  IconButton,
  TableRow,
  TableBody,
  TableCell,
  Container,
  Typography,
  TableContainer,
  TablePagination,
  Dialog,
  DialogTitle,
  DialogContent,
  TextField,
  DialogActions,
  InputLabel,
  Select,
  MenuItem,
  FormControl,
  Box
} from '@mui/material';

// material-lab
import AdapterDateFns from '@mui/lab/AdapterDateFns';
import LocalizationProvider from '@mui/lab/LocalizationProvider';
import DatePicker from '@mui/lab/DatePicker';

//icons-eva
import plusFill from '@iconify/icons-eva/plus-fill';
import editFill from '@iconify/icons-eva/edit-fill';
import trash2Outline from "@iconify/icons-eva/trash-2-outline";

// components
import Page from '../../../components/Page';
import Label from '../../../components/Label';
import Scrollbar from '../../../components/Scrollbar';
import SearchNotFound from '../../../components/SearchNotFound';
import { UserListHead, UserListToolbar, UserMoreMenu } from '../../../components/_dashboard/user';
//
import USERLIST from '../../../_mocks_/user';

import { fetchAjax, postAjax, putAjax, deleteAjax } from '../../../request';
import { systemUsersService } from '../../../API/system/system-user.service';

import { mockImgAvatar } from '../../../utils/mockImages';

const UserContext = React.createContext();

const queryParams = {
  sort: ''
}

const initialValues = {
  name: '',
  email: '',
  password: '',
  gender: '',
  avatarUrl: '',
  dob: new Date()
}

function reducer(state, action) {
  switch (action.type) {
    case 'SEARCH_FORM':
      return action.data;
    case 'OPEN_DIALOG':
      return action.data;
    default:
      return queryParams;
  }
}


// ----------------------------------------------------------------------
const HEAD_CELLS = [
  {
    id: 'id',
    dataIndex: 'id',
    label: 'ID',
    alignRight: false,
    isDisplay: true,
  },
  {
    id: 'name',
    dataIndex: 'name',
    label: 'Name',
    alignRight: false,
    isDisplay: true,
    customRender: ({record})=>{
      const { id, name, avatarUrl } = record;
      return(
        <Stack direction="row" alignItems="center" spacing={2}>
          <Avatar alt={name} src={avatarUrl?avatarUrl:mockImgAvatar(24)} />
          <Typography variant="subtitle2" noWrap>
            <RouterLink to={`${id}`} style={{color: '#212B36'}}>
              {name}
            </RouterLink>
          </Typography>
        </Stack>
      )
    }
  },
  {
    id: 'gender',
    dataIndex: 'gender',
    label: 'Gender',
    alignRight: false,
    isDisplay: true,
    customRender: ({record})=>{
      const { gender } = record;
      const genderMap = new Map([
          ['0', 'Males'],
          ['1', 'Females'],
          ['2', '******'] //Secret
      ]);
      const genderKey = genderMap.get(gender);
      return(
          <Stack direction="row" alignItems="center" spacing={2}>
            <Typography variant="subtitle2" noWrap>
              {genderKey}
            </Typography>
          </Stack>
      )
    }
  },
  {
    id: 'email',
    dataIndex: 'email',
    label: 'Email',
    alignRight: false,
    isDisplay: true,
  },
  {
    id: 'dob',
    dataIndex: 'dob',
    label: 'DOB',
    alignRight: false,
    isDisplay: true,
  },
  {
    id: '',
    dataIndex: 'Action',
    label: 'Action',
    alignRight: false,
    isDisplay: true,
    customRender: ({ record, handleEdit, handleDelete }) => {
      return (
          <>
            <IconButton onClick={() => handleEdit(record)}>
              <Icon icon={editFill} width={24} height={24} />
            </IconButton>
            <IconButton onClick={() => handleDelete(record)}>
              <Icon icon={trash2Outline} width={24} height={24} />
            </IconButton>
          </>
      )
    }
  }
];

const TABLE_HEAD = [
  {
    id: 'name',
    label: 'Name',
    alignRight: false
  },
  {
    id: 'company',
    label: 'Company',
    alignRight: false
  },
  {
    id: 'role',
    label: 'Role',
    alignRight: false
  },
  {
    id: 'isVerified',
    label: 'Verified',
    alignRight: false
  },
  {
    id: 'status',
    label: 'Status',
    alignRight: false
  },
  {
    id: ''
  }
];

// ----------------------------------------------------------------------

function descendingComparator(a, b, orderBy) {
  if (b[orderBy] < a[orderBy]) {
    return -1;
  }
  if (b[orderBy] > a[orderBy]) {
    return 1;
  }
  return 0;
}

function getComparator(order, orderBy) {
  return order === 'desc'
    ? (a, b) => descendingComparator(a, b, orderBy)
    : (a, b) => -descendingComparator(a, b, orderBy);
}

function applySortFilter(array, comparator, query) {
  const stabilizedThis = array.map((el, index) => [el, index]);
  stabilizedThis.sort((a, b) => {
    const order = comparator(a[0], b[0]);
    if (order !== 0) return order;
    return a[1] - b[1];
  });
  if (query) {
    return filter(array, (_user) => _user.name.toLowerCase().indexOf(query.toLowerCase()) !== -1);
  }
  return stabilizedThis.map((el) => el[0]);
}


function EnhancedTable() {

  const { state, dispatch } = useContext(UserContext);

  const [tableList, setTableList] = useState([]);
  const [page, setPage] = useState(0);
  const [rowsPerPage, setRowsPerPage] = useState(5);
  const [order, setOrder] = useState('asc');
  const [selected, setSelected] = useState([]);
  const [orderBy, setOrderBy] = useState('name');
  const [filterName, setFilterName] = useState('');
  const [filterEmail, setFilterEmail] = useState('');
  const [filterAge, setFilterAge] = useState(18);
  const [filterGender, setFilterGender] = useState('');
  const [filterColums, setFilterColums] = useState([...HEAD_CELLS]);

  const [excelData, setExcelData] = useState([])

  const handleEdit = (record)=>{
    dispatch({
      type: 'OPEN_DIALOG',
      data: {
        title: record?.id ? '编辑' :'新增',
        open: true,
        initialValues: record?.id ? record : initialValues
      }
    });
  }

  const handleDelete = async (record)=>{
    const response = await fetch(`/api/system/user/${record.id}`, {
      method: 'DELETE', // *GET, POST, PUT, DELETE, etc.
      mode: 'cors', // no-cors, *cors, same-origin
      cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
      credentials: 'same-origin', // include, *same-origin, omit
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded',
      },
      redirect: 'follow', // manual, *follow, error
      referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
      // body: JSON.stringify({ userId: record.id  }) // body data type must match "Content-Type" header
    });
    console.log(response.json())
  }

  const handleRequestSort = (event, property) => {
    const isAsc = orderBy === property && order === 'asc';
    setOrder(isAsc ? 'desc' : 'asc');
    setOrderBy(property);
  };

  const handleSelectAllClick = (event) => {
    if (event.target.checked) {
      const newSelecteds = tableList.map((n) => n.id);
      setSelected(newSelecteds);
      return;
    }
    setSelected([]);
  };

  const handleSelectItemClick = (event, id) => {
    const selectedIndex = selected.indexOf(id);
    let newSelected = [];
    if (selectedIndex === -1) {
      newSelected = newSelected.concat(selected, id);
    } else if (selectedIndex === 0) {
      newSelected = newSelected.concat(selected.slice(1));
    } else if (selectedIndex === selected.length - 1) {
      newSelected = newSelected.concat(selected.slice(0, -1));
    } else if (selectedIndex > 0) {
      newSelected = newSelected.concat(
          selected.slice(0, selectedIndex),
          selected.slice(selectedIndex + 1)
      );
    }
    setSelected(newSelected);
  };

  const handleChangePage = (event, newPage) => {
    setPage(newPage);
  };

  const handleChangeRowsPerPage = (event) => {
    setRowsPerPage(event.target.value);
    setPage(0);
  };

  const handleFilterByName = (event) => {
    const { value } = event.target;
    setFilterName(value);
  };

  const handleFilterByColums = ({ target: { value, checked } }, { isDisplay }) => {
    if(checked){
      setFilterColums(_.map(filterColums, colum=>{
        if([value].includes(colum.id)) colum.isDisplay = true;
        return colum;
      }));
    }else{
      setFilterColums(_.map(filterColums, colum=>{
        if([value].includes(colum.id)) colum.isDisplay = false;
        return colum;
      }));
    }
  };

  const handleFilterByGender = (event) => {
    const { value } = event.target;
    setFilterGender(value);
  }

  const emptyRows = page > 0 ? Math.max(0, rowsPerPage - tableList.length) : 0;

  const isUserNotFound = tableList.length === 0;

  useEffect(()=>{
    systemUsersService.ApiSearchUsers({
      offset: page,
      pageSize: rowsPerPage,
      name: filterName,
      email: filterEmail,
      age: filterAge,
      gender: filterGender,
      fieldBy: orderBy,
      field: order
    }).then(res=>{
      const { status, message, data } = res;
      const { content } = data;
      if(status === 100 && content){
        setTableList(content);
        setExcelData(Array.isArray(content) ? _.map(content, ({ id, name, email, dob })=>({ id, name, email, dob })) : []);
      }
    });
  }, [filterName, filterEmail, filterAge, filterGender, orderBy, order, page, rowsPerPage])

  return (
      <Page title="User | Minimal-UI">
        <Container>
          <Stack direction="row" alignItems="center" justifyContent="space-between" mb={5}>
            <Typography variant="h4" gutterBottom>
              User
            </Typography>
            <Button
                variant="contained"
                startIcon={<Icon icon={plusFill} />}
                onClick={()=>handleEdit({})}
            >
              New User
            </Button>
          </Stack>

          <Card>
            <UserListToolbar
                headLabel={filterColums}
                excelData={excelData}
                numSelected={selected.length}
                filterName={filterName}
                onFilterName={handleFilterByName}
                onChangeDisplayColums={handleFilterByColums}
            />

            <Box sx={{ minWidth: '100%' }}>
              <FormControl fullWidth>
                <InputLabel id="demo-simple-select-label">Gender</InputLabel>
                <Select
                    labelId="demo-simple-select-label"
                    id="demo-simple-select"
                    value={filterGender}
                    label="Gender"
                    onChange={handleFilterByGender}
                >
                  <MenuItem value={`0`}>Male</MenuItem>
                  <MenuItem value={`1`}>Female</MenuItem>
                  <MenuItem value={`2`}>保密</MenuItem>
                </Select>
              </FormControl>
            </Box>

            <Scrollbar>
              <TableContainer sx={{ minWidth: 800 }}>
                <Table>
                  <UserListHead
                      order={order}
                      orderBy={orderBy}
                      headLabel={filterColums}
                      rowCount={tableList.length}
                      numSelected={selected.length}
                      onRequestSort={handleRequestSort}
                      onSelectAllClick={handleSelectAllClick}
                  />
                  <TableBody>
                    {tableList
                      .map((row) => {
                        const { id } = row;
                        const isItemSelected = selected.indexOf(id) !== -1;

                        return(
                          <TableRow
                              hover
                              key={id}
                              tabIndex={-1}
                              role="checkbox"
                              selected={isItemSelected}
                              aria-checked={isItemSelected}
                          >
                            <TableCell padding="checkbox">
                              <Checkbox
                                checked={isItemSelected}
                                onChange={(event) => handleSelectItemClick(event, id)}
                              />
                            </TableCell>
                            {
                              _.map(filterColums, (cell, idx) => {
                                const { customRender: CustomRender, isDisplay } = cell;
                                return isDisplay && (
                                  CustomRender ? (
                                    <TableCell key={idx} align={cell.align}>
                                      <CustomRender key={idx} sequence={id} record={row} handleEdit={handleEdit} handleDelete={handleDelete} />
                                    </TableCell>
                                  ) : (
                                    <TableCell key={Math.random() + idx} align={cell.align}>{row[cell.dataIndex]}</TableCell>
                                  )
                                )
                              })
                            }
                          </TableRow>
                        )
                      })}
                    {emptyRows > 0 && (
                        <TableRow style={{ height: 73 * emptyRows }}>
                          <TableCell colSpan={6} />
                        </TableRow>
                    )}
                  </TableBody>
                  {isUserNotFound && (
                    <TableBody>
                      <TableRow>
                        <TableCell align="center" colSpan={6} sx={{ py: 3 }}>
                          <SearchNotFound searchQuery={filterName} />
                        </TableCell>
                      </TableRow>
                    </TableBody>
                  )}
                </Table>
              </TableContainer>
            </Scrollbar>

            <TablePagination
                rowsPerPageOptions={[5, 10, 25]}
                component="div"
                count={USERLIST.length}
                rowsPerPage={rowsPerPage}
                page={page}
                onPageChange={handleChangePage}
                onRowsPerPageChange={handleChangeRowsPerPage}
            />
          </Card>
        </Container>
      </Page>
  );
}

function ExampleTable(){

  const [page, setPage] = useState(0);
  const [order, setOrder] = useState('asc');
  const [selected, setSelected] = useState([]);
  const [orderBy, setOrderBy] = useState('name');
  const [filterName, setFilterName] = useState('');
  const [rowsPerPage, setRowsPerPage] = useState(5);

  const handleRequestSort = (event, property) => {
    const isAsc = orderBy === property && order === 'asc';
    setOrder(isAsc ? 'desc' : 'asc');
    setOrderBy(property);
  };

  const handleSelectAllClick = (event) => {
    if (event.target.checked) {
      const newSelecteds = USERLIST.map((n) => n.name);
      setSelected(newSelecteds);
      return;
    }
    setSelected([]);
  };

  const handleSelectItemClick = (event, name) => {
    const selectedIndex = selected.indexOf(name);
    let newSelected = [];
    if (selectedIndex === -1) {
      newSelected = newSelected.concat(selected, name);
    } else if (selectedIndex === 0) {
      newSelected = newSelected.concat(selected.slice(1));
    } else if (selectedIndex === selected.length - 1) {
      newSelected = newSelected.concat(selected.slice(0, -1));
    } else if (selectedIndex > 0) {
      newSelected = newSelected.concat(
          selected.slice(0, selectedIndex),
          selected.slice(selectedIndex + 1)
      );
    }
    setSelected(newSelected);
  };

  const handleChangePage = (event, newPage) => {
    setPage(newPage);
  };

  const handleChangeRowsPerPage = (event) => {
    setRowsPerPage(parseInt(event.target.value, 10));
    setPage(0);
  };

  const handleFilterByName = (event) => {
    setFilterName(event.target.value);
  };

  const emptyRows = page > 0 ? Math.max(0, (1 + page) * rowsPerPage - USERLIST.length) : 0;

  const filteredUsers = applySortFilter(USERLIST, getComparator(order, orderBy), filterName);

  const isUserNotFound = filteredUsers.length === 0;

  return (
      <Page title="User | Minimal-UI">
        <Container>
          <Stack direction="row" alignItems="center" justifyContent="space-between" mb={5}>
            <Typography variant="h4" gutterBottom>
              User
            </Typography>
            <Button
                variant="contained"
                component={RouterLink}
                to="#"
                startIcon={<Icon icon={plusFill} />}
            >
              New User
            </Button>
          </Stack>

          <Card>
            <UserListToolbar
                numSelected={selected.length}
                filterName={filterName}
                onFilterName={handleFilterByName}
            />

            <Scrollbar>
              <TableContainer sx={{ minWidth: 800 }}>
                <Table>
                  <UserListHead
                      order={order}
                      orderBy={orderBy}
                      headLabel={TABLE_HEAD}
                      rowCount={USERLIST.length}
                      numSelected={selected.length}
                      onRequestSort={handleRequestSort}
                      onSelectAllClick={handleSelectAllClick}
                  />
                  <TableBody>
                    {filteredUsers
                        .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
                        .map((row) => {
                          const { id, name, role, status, company, avatarUrl, isVerified } = row;
                          const isItemSelected = selected.indexOf(name) !== -1;

                          return (
                              <TableRow
                                  hover
                                  key={id}
                                  tabIndex={-1}
                                  role="checkbox"
                                  selected={isItemSelected}
                                  aria-checked={isItemSelected}
                              >
                                <TableCell padding="checkbox">
                                  <Checkbox
                                      checked={isItemSelected}
                                      onChange={(event) => handleSelectItemClick(event, name)}
                                  />
                                </TableCell>
                                <TableCell component="th" scope="row" padding="none">
                                  <Stack direction="row" alignItems="center" spacing={2}>
                                    <Avatar alt={name} src={avatarUrl} />
                                    <Typography variant="subtitle2" noWrap>
                                      {name}
                                    </Typography>
                                  </Stack>
                                </TableCell>
                                <TableCell align="left">{company}</TableCell>
                                <TableCell align="left">{role}</TableCell>
                                <TableCell align="left">{isVerified ? 'Yes' : 'No'}</TableCell>
                                <TableCell align="left">
                                  <Label
                                      variant="ghost"
                                      color={(status === 'banned' && 'error') || 'success'}
                                  >
                                    {sentenceCase(status)}
                                  </Label>
                                </TableCell>

                                <TableCell align="right">
                                  <UserMoreMenu />
                                </TableCell>
                              </TableRow>
                          );
                        })}
                    {emptyRows > 0 && (
                        <TableRow style={{ height: 53 * emptyRows }}>
                          <TableCell colSpan={6} />
                        </TableRow>
                    )}
                  </TableBody>
                  {isUserNotFound && (
                      <TableBody>
                        <TableRow>
                          <TableCell align="center" colSpan={6} sx={{ py: 3 }}>
                            <SearchNotFound searchQuery={filterName} />
                          </TableCell>
                        </TableRow>
                      </TableBody>
                  )}
                </Table>
              </TableContainer>
            </Scrollbar>

            <TablePagination
                rowsPerPageOptions={[5, 10, 25]}
                component="div"
                count={USERLIST.length}
                rowsPerPage={rowsPerPage}
                page={page}
                onPageChange={handleChangePage}
                onRowsPerPageChange={handleChangeRowsPerPage}
            />
          </Card>
        </Container>
      </Page>
  );
}

const BuildDialog = ({}) => {


  const { state, dispatch } = useContext(UserContext);

  const formik = useFormik({
    initialValues: state.initialValues,
    onSubmit: (values, event) => {
      values.id ? putAjax(`/api/system/user`, values).then(data=>{
        console.log('hello',data);
        handleClose();
      }) : postAjax(`/api/system/user`, values).then(data=>{
        console.log('world',data);
        handleClose();
      })
    },
  });


  const handleFormSubmit = () => {
    formik.handleSubmit()
  }

  const handleClose = () => {
    dispatch({ type: 'OPEN_DIALOG', data: { ...state, open: false, initialValues }});
  }

  useEffect(()=>{
    formik.setValues(state?.initialValues)
  }, [state?.initialValues])

  return (
      <Dialog open={!!state.open} onClose={handleClose}  fullWidth aria-labelledby="user-dialog-title">
        <DialogTitle id="user-dialog-title">{state?.title}</DialogTitle>
        <DialogContent sx={{ pt: '10px !important' }}>
          <form>

            <TextField
              id="user-name"
              sx={{ mb: 2 }}
              fullWidth
              type="text"
              size="small"
              label="User Name"
              name="name"
              value={formik.values?.name || ''}
              onChange={formik.handleChange}
            />

            {
              (!formik.values?.id) &&
              <TextField
                id="user-password"
                sx={{ mb: 2 }}
                fullWidth
                type="text"
                size="small"
                label="Password"
                name="password"
                value={formik.values?.password || ''}
                onChange={formik.handleChange}
              />
            }

            <TextField
              id="user-email"
              sx={{ mb: 2 }}
              fullWidth
              type="text"
              size="small"
              label="Email"
              name="email"
              value={formik.values?.email || ''}
              onChange={formik.handleChange}
            />

            <FormControl fullWidth size="small">
              <InputLabel id="user-gender-outlined">Gender</InputLabel>
              <Select
                  labelId="user-gender-outlined"
                  id="user-gender"
                  sx={{ mb: 2 }}
                  label="Gender"
                  name="gender"
                  value={formik.values?.gender || ''}
                  onChange={formik.handleChange}
              >
                <MenuItem value={`0`}>男</MenuItem>
                <MenuItem value={`1`}>女</MenuItem>
                <MenuItem value={`2`}>保密</MenuItem>
              </Select>
            </FormControl>

            <LocalizationProvider dateAdapter={AdapterDateFns}>
              <DatePicker
                  sx={{ mb: 2 }}
                  label="Dob"
                  name="dob"
                  value={formik.values?.dob || ''}
                  onChange={(newValue) => {
                    formik.setFieldValue('dob', newValue)
                  }}
                  renderInput={(params) => <TextField size="small" fullWidth {...params} />}
              />
            </LocalizationProvider>

          </form>
        </DialogContent>
        <DialogActions>
          <Button onClick={handleClose}>取消</Button>
          <Button onClick={handleFormSubmit} autoFocus>
            提交
          </Button>
        </DialogActions>
      </Dialog>
  );
}

export default function User() {

  const [state, dispatch] = useReducer(reducer, { queryParams });

  return (
      <UserContext.Provider value={{ state, dispatch }}>
        <EnhancedTable />
        {/*<ExampleTable />*/}

        <BuildDialog />
        {/*{
          state.open &&
          <BuildDialog />
        }*/}
      </UserContext.Provider>
  );
}
